#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netdb.h> 
#include <unistd.h>
#include <pthread.h>
#include <ncurses.h>

#include <checks.h>
#include <network.h>
#include <MyInterface.h>

/*									*/
struct hostent *server;
struct sockaddr_in serveraddr;
WINDOW *board;
int port = 2012;
int sockfd = 0;
/*									*/


void strtoint (int *i, char ch, char ch2)
{
	switch(ch){
		case '0': *i = 0; break;
		case '1': *i = 1; break;
		case '2': *i = 2; break;
		case '3': *i = 3; break;
		case '4': *i = 4; break;
		case '5': *i = 5; break;
		case '6': *i = 6; break;
		case '7': *i = 7; break;
		case '8': *i = 8; break;
		case '9': *i = 9; break;
		default:
			if (ch=='-'){
				if (ch2=='1') *i=-1;
				if (ch2=='2') *i=-2;
				}

			break;
	}
}

void exitNow(char *msg){ // Выводит сообщение и выходит.
	if (msg != NULL){
		printf("%s\n", msg);
	}
	if (sockfd > 0){
		close(sockfd);
	}
	exit(0);
}

void scanArgs(int argc, char *argv[]){ // Сканирование аргуентов
	struct option long_options[] = {
		 {"server", required_argument, NULL, 's'},
		 {"port", required_argument, NULL, 'p'},
		 {0, 0, 0, 0} 
	     };
	char arg; 

	while ((arg = getopt_long(argc, argv, "s:p:", long_options, NULL)) != -1){
		switch (arg){
			case 's': 
				    server = gethostbyname(optarg); // domain -> ip
    				if (server == NULL) {
						exitNow("Ошибка. Неверное имя сервера.");
   					 }
				break;
				
			case 'p':
				port = atoi(optarg);
				if ((1024 > port) || (port > 65536))
					exitNow("Ошибка. Неверный порт.");
				break;
			default:
				exitNow("[-s|--server IP сервера] [-p|--port Номер порта]");
		}
	}

    if (server == NULL){
		server = gethostbyname("localhost");
    }
}

void networkInitialization(){
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        exitNow("Ошибка при создании сокета.");
	
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    bcopy((char *)server->h_addr, (char *)&serveraddr.sin_addr.s_addr, server->h_length);

    if (connect(sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0) 
        exitNow("Ошибка при установке соединения.");
    
    if ((gameaddr = malloc(sizeof(struct gamelist) * 200)) == NULL){ // Резервируем память под клиентов
		exitNow("Ошибка. Не достаточно памяти (clients)");
	}
	int i;
	for (i = 0; i < 200; i++)	{
		gameaddr[i].id = -1;
	}
}

void manualControl(){
	printf("Включен ручной контроль отправки пакетов!\n");
	char msg[256];
	int code;
	while(sockfd > 0){
		printf("Код:");
		scanf("%d",&code);
		printf("Сообщение:");
		scanf("%s",msg);
		sending(sockfd, code, msg);
	}
}

void *network(){
	
	char *receiveMessage;
	int code;
	gameListStatus = 0;
	numbergames = 0;
	while((sockfd > 0) && ((recv(sockfd, &code, sizeof(int), MSG_PEEK)) > 0)){
		receiveMessage = receiving(sockfd);
		switch(code){
			case GAMEADDR:{
																	 //                      _____  _____
				char *name;                                          // \    /  \    / |   |   |   |    |
				int game;                                            //  \  /    \  /  |   |   |   |    |
				name = strchr(receiveMessage, 'G') + 1;              //   \/      \/   |   |   |   |____|
				game = strlen(receiveMessage) - strlen(name) - 1;    //   /\      /    |  /|   |   |    |
				receiveMessage[game] = '\0';                         //  /  \    /     | / |   |   |    |
				game = atoi(receiveMessage);                         // /    \  /      |/  |   |   |    |
				gameaddr[numbergames].id = game;
				strncpy(gameaddr[numbergames].name, name, sizeof(gameaddr[numbergames].name));
				gameaddr[numbergames].color = '0';
				numbergames++;
				break;
			}
			case NOTGAMES:{
				gameListStatus = 1;
				break;
			}
			case ALLGAMES:{
				gameListStatus = 1;
				break;
			}
			case CREATEOK:{
				/*Вызов отрисовки поля*/
				break;
			}
			case CHAT:{
				print_message(receiveMessage, 0);
		//		show_error(receiveMessage);
		//		//printf("Разведка доложила: %s\n", receiveMessage);
				break;
			}
			case YOUHERE:{
		//		printf("Вы здесь: %s\n", receiveMessage);
				break;
			}
			case ECHOREQ:{
		//		printf("%s\n", receiveMessage);
				break;
			}
			case WRONGCODE:{
		//		printf("Поки!\n");
				break;
			}
			case JOINED:{
				break;
			}
			case ENEMYFLED:{
		//		printf("Противник бежал.\n");
				break;
			}
			case MOVED:{
				int i, j=0;
				int moved[9];
				for (i=0; i<9+j; i++)
					{	
					strtoint(&moved[i-j], receiveMessage[i], receiveMessage[i+1]);
					if (receiveMessage[i]=='-') {i++;j++;}			//Да, стыдно, но иначе никак
					//move[i]= (int) receiveMessage[i];
					}
				
				give_me_move_main(moved);
			}
			case STARTGAME:{
				sending(sockfd, READY, NULL);
				break;
			}
			default:{
				break;
			}
		}
	}
	printf("\n:(\n");
	exitNow(NULL);
	return NULL;
}

int main(int argc, char *argv[])
{
	scanArgs(argc, argv);
	networkInitialization();
	pthread_t netThread;
	pthread_create(&netThread, NULL, network, NULL);
//	manualControl();
	main_menu();
	return 0;
}

